/*
  S.M.A.C.K - An operating system kernel
  Copyright (C) 2010,2011 Mattias Holm and Kristian Rietveld
  For licensing and a full list of authors of the kernel, see the files
  COPYING and AUTHORS.
*/

#include <string.h>
#include <stdint.h>

void*
memcpy(void *restrict s1, const void *restrict s2, size_t n)
{
  // Common case where buffers are aligned at word boundaries
  if (((n | (uintptr_t)s1 | (uintptr_t)s2) % 4) == 0) {
    uint32_t * restrict p1 = s1;
    const uint32_t * restrict p2 = s2;
    for (size_t i = 0 ; i < n/4 ; i ++) {
      p1[i] = p2[i];
    }
    return s1;
  }

  char * restrict p1 = s1;
  const char * restrict p2 = s2;

  for (size_t i = 0 ; i < n ; i ++) {
    p1[i] = p2[i];
  }
  return s1;
}


void*
memset(void *b, int c, size_t len)
{
  char *p1 = b;

  // TODO: Optimise for alignment and sizes
  for (size_t i = 0 ; i < len ; i ++) {
    p1[i] = c;
  }
  return b;
}

int
strbcmp(const char *s1, const char *s2)
{
  while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) {
    s1++;
    s2++;
  }
  return *s1 - *s2;
}

int
strncmp(const char *s1, const char *s2, int len)
{
  int i = 0;

  while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2 && i < len - 1) {
    s1++;
    s2++;
    i++;
  }

  return *s1 - *s2;
}

char*
strchr(const char *s, int c)
{
  while (*s && *s != c) s ++;
  if (*s == '\0') return NULL;
  return (char*)s;
}


size_t
strlcpy(char * s1, const char * s2, size_t n)
{
  int i = 0;
  for (i = 0 ; i < n-1 && s2[i] ; i ++) {
    s1[i] = s2[i];
  }
  s1[i] = '\0';
  while (s2[i] != '\0') i ++;

  return i;
}

size_t
strnlen(const char *s, size_t n)
{
  int i = 0;
  for (i = 0; i < n && s[i] != '\0'; i++);

  return i;
}
